#include <Windows.h>
#include "TriangleDemo.h"
#include <memory>
#include "CrubeDemo.h"
#include "SphereDemo.h"
#include "MeshDemo.h"
#include "EffecDemo.h"
#include "Camera.h"
#include "RenderManager.h"
#include "MeshDemo.h"
#include "Level.h"
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);


Camera* TheCamera;
Level* TheLevel;
void Updata()
{
	static float t = 0.0f;
	static ULONGLONG timeStart = 0;
	ULONGLONG timeCur = GetTickCount64();
	if (timeStart == 0)
		timeStart = timeCur;
	t = (timeCur - timeStart) / 1000.f;
	timeStart = timeCur;
	if (::GetAsyncKeyState('W') * 0x8000f)
	{
		TheCamera->Walk(4.0f*t);
	}
	if (::GetAsyncKeyState('S') * 0x8000f)
	{
		TheCamera->Walk(-4.0f*t);
	}
	if (::GetAsyncKeyState('D') * 0x8000f)
	{
		TheCamera->Strafe(4.0f*t);
	}
	if (::GetAsyncKeyState('A') * 0x8000f)
	{
		TheCamera->Strafe(-4.0f*t);
	}

	if (::GetAsyncKeyState('Q') * 0x8000f)
	{
		TheCamera->Fly(4.0f*t);
	}

	if (::GetAsyncKeyState('E') * 0x8000f)
	{
		TheCamera->Fly(-4.0f*t);
	}

	TheCamera->UpdateViewMatrix();

}
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nShowCmd)
{
	WNDCLASSEX wcex;
	wcex.cbClsExtra = 0;
	wcex.cbSize = sizeof(wcex);
	wcex.cbWndExtra = 0;
	wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
	wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
	wcex.hIcon = LoadIcon(NULL, IDI_WINLOGO);
	wcex.hIconSm = wcex.hIcon;
	wcex.hInstance = hInstance;
	wcex.lpfnWndProc = WndProc;
	wcex.lpszClassName = L"BlankDemo";
	wcex.lpszMenuName = L"BlankDemo";
	wcex.style = CS_HREDRAW | CS_VREDRAW;

	if (!RegisterClassEx(&wcex))
		return -1;


	RECT rc = { 0, 0, 1024, 768 };
	AdjustWindowRect(&rc, WS_OVERLAPPEDWINDOW, false);

	HWND hwnd = CreateWindowEx(WS_EX_APPWINDOW, L"BlankDemo", L"BlankDemo", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT,
		CW_USEDEFAULT, rc.right - rc.left, rc.bottom - rc.top, NULL, NULL, hInstance, NULL);

	if (!hwnd)
		return -1;
	ShowWindow(hwnd, nShowCmd);
	bool result = RenderManager::GetRenderManagerInstance()->Initialize(hInstance, hwnd);
	if (!result)
	{
		return -1;
	}
	TheCamera = new Camera();
	XMVECTOR Eye = XMVectorSet(0.0f, 0.f, -50.f, 0.0f);
	XMVECTOR At = XMVectorSet(0.0f, 0.f, 0.0f, 0.0f);
	XMVECTOR Up = XMVectorSet(0.0f, 1.0f, 0.0f, 0.0f);
	if (TheCamera)
	{
		TheCamera->LookAtXM(Eye, At, Up);
		TheCamera->SetLens(XM_PIDIV2 / 6, 1024.f / 768.f, 0.01f, 200.0f);
	}
	TheLevel = new Level();
	MeshDemo*p = new MeshDemo();
	if (p->LoadContent())
	{
		p->SetTheCamera(TheCamera);
		TheLevel->AddActor(p, XMFLOAT3(-5.f, 0.f, 0.f));
	}
	else
	{
		delete p;
		p = nullptr;
	}
	p = new MeshDemo();
	if (p->LoadContent())
	{
		p->SetTheCamera(TheCamera);
		TheLevel->AddActor(p, XMFLOAT3(5.f, 0.f, 0.f));
	}
	else
	{
		delete p;
		p = nullptr;
	}
	CrubeDemo*c = new CrubeDemo();
	if (c->LoadContent())
	{
		c->SetTheCamera(TheCamera);
		TheLevel->AddActor(c, XMFLOAT3(0.f, 0.f, 0.f));
	}
	else
	{
		delete c;
		c = nullptr;
	}

	EffecDemo*e = new EffecDemo();
	if (e->LoadContent())
	{
		e->SetTheCamera(TheCamera);
		TheLevel->AddActor(e, XMFLOAT3(0.f, 0.f, 0.f));
	}
	else
	{
		delete e;
		e = nullptr;
	}

	SphereDemo*s = new SphereDemo();
	if (s->LoadContent())
	{
		s->SetTheCamera(TheCamera);
		TheLevel->AddActor(s, XMFLOAT3(0.f, 0.f, 0.f));
	}
	else
	{
		delete s;
		s = nullptr;
	}

	MSG msg;
	ZeroMemory(&msg, sizeof(msg));
	while (msg.message != WM_QUIT)
	{
		if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
		{
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
		Updata();
		TheLevel->Updata();
		RenderManager::GetRenderManagerInstance()->BeginRender();
		TheLevel->RenderLevel();
		RenderManager::GetRenderManagerInstance()->EndRender();
	}
	return static_cast<int>(msg.wParam);
}




LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	PAINTSTRUCT paintStruct;
	HDC hDc;
	switch (message)
	{
	case WM_PAINT:
		hDc = BeginPaint(hWnd, &paintStruct);
		EndPaint(hWnd, &paintStruct);
		break;
	case WM_DESTROY:
		PostQuitMessage(0);
		break;
	default:
		return DefWindowProc(hWnd, message, wParam, lParam);
	}
	return 0;
}
